package com.cloudfun.campusshare.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cloudfun.campusshare.common.constant.Code;
import com.cloudfun.campusshare.common.constant.DevicePlatform;
import com.cloudfun.campusshare.common.model.vo.*;
import com.cloudfun.campusshare.common.response.BaseResult;
import com.cloudfun.campusshare.common.response.BaseResultFactory;
import com.cloudfun.campusshare.common.security.AuthenticationHolder;
import com.cloudfun.campusshare.entity.DeviceEntity;
import com.cloudfun.campusshare.entity.InvokeHistoryEntity;
import com.cloudfun.campusshare.service.AbstractDeviceOpService;
import com.cloudfun.campusshare.service.InvokeHistoryService;
import com.cloudfun.campusshare.service.UhomeService;
import com.cloudfun.campusshare.util.JsonUtil;
import com.cloudfun.campusshare.util.haier.OperateParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

/**
 * Created by Huqin on 2020/3/23
 */
@Slf4j
@Component
public class UHomeDeviceOpServiceImpl extends AbstractDeviceOpService {

    @Autowired
    private InvokeHistoryService invokeHistoryService;

    @Autowired
    private UhomeService uhomeService;

    @Override
    public DevicePlatform supportPlatform() {
        return DevicePlatform.UHOME;
    }

    @Override
    public BaseResult doGetPropertyByName(DeviceEntity deviceEntity, String propertyName) {
        if (Objects.isNull(deviceEntity)) {
            return BaseResultFactory.produceEmptyResult(Code.NODATA);
        }
        Map<String, String> map = new HashMap<>();
        map.put("deviceId", deviceEntity.getImei());
        map.put("attributeName", propertyName);
        // 请求
        String respResult = this.getLocalAttrByName(deviceEntity.getId(), propertyName);
        if (null == respResult) {
            respResult = this.executeRequest("/modfier/getAttributeByName", map);
        }
        Map resMap = JsonUtil.GetJsonMap(respResult);
        Object valueObj = resMap.get("value");
        String value = valueObj == null ? null : valueObj.toString();
        boolean success = resMap.get("retCode").equals("000000");
        // save invoke history
        InvokeHistoryEntity historyEntity = InvokeHistoryEntity.builder()
                .method("getAttributeByName")
                .param(JSONObject.toJSONString(map))
                .orderId(null)
                .result(respResult)
                .resultStatus(success ? "SUCCESS" : "FAILED")
                .userId(AuthenticationHolder.getUserId())
                .function("getPropertyByName")
                .deviceId(deviceEntity.getId())
                .build();
        invokeHistoryService.create(historyEntity);
        return BaseResultFactory.produceResult(Code.SUCCESS, value);
    }

    @Override
    public BaseResult doDeviceOnline(DeviceEntity deviceEntity) {
        Map<String, String> paramsMap = new HashMap<>();
        paramsMap.put("deviceId", deviceEntity.getImei());
        return this.executeRequest(deviceEntity.getId(), "/isOnline", paramsMap, "isOnline", "isOnline");
    }

    @Override
    public BaseResult doReset(DeviceEntity deviceEntity) {
        OperateParam param = new OperateParam();
        param.setImei(deviceEntity.getImei());
        Map<String, String> cmdMap = new HashMap<>();
        cmdMap.put("returnStandby", "1");
        param.setCmdArgs(cmdMap);
        log.info("imei: " + deviceEntity.getImei());
        return this.executeRequest(deviceEntity.getId(), "/modfier/operate", param, "returnStandby", "reset");
    }

    @Override
    public BaseResult doWash(DeviceEntity deviceEntity, RollerWasherOpVO rollerWasherOpVO) {
        OperateParam param = new OperateParam();
        param.setImei(rollerWasherOpVO.getImei());
        param.setCmdName("grCommonWashCW");
        Map<String, String> cmdMap = new LinkedHashMap<>();
        cmdMap.put("laundryCycleCW", rollerWasherOpVO.getWashType());
        param.setCmdArgs(cmdMap);
        log.info("deviceId: " + deviceEntity.getId());
        return this.executeRequest(deviceEntity.getId(), "/modfier/operate", param, "operate", rollerWasherOpVO.getOrderId(), "wash");
    }

    @Override
    public BaseResult doDrying(DeviceEntity deviceEntity, DryerOperateVO deviceDryingVO) {
        OperateParam param = new OperateParam();
        param.setImei(deviceDryingVO.getImei());
        param.setCmdName("grCommonSetCD");
        Map<String, String> cmdMap = new LinkedHashMap<>();
        cmdMap.put("tempLevel", deviceDryingVO.getTempLevel() == null ? null : deviceDryingVO.getTempLevel().toString());
        cmdMap.put("waitingTime", deviceDryingVO.getWaitingTime() == null ? null : deviceDryingVO.getWaitingTime().toString());
        cmdMap.put("dryTime", deviceDryingVO.getDryTime() == null ? null : deviceDryingVO.getDryTime().toString());
        cmdMap.put("startEnabled", deviceDryingVO.getStartEnabled() == null ? null : deviceDryingVO.getStartEnabled().toString());
        param.setCmdArgs(cmdMap);
        log.info("deviceId: " + deviceEntity.getId());
        return executeRequest(deviceEntity.getId(), "/modfier/operate", param, "operate", deviceDryingVO.getOrderId(), "dry");
    }

    @Override
    public BaseResult doPulseWash(DeviceEntity deviceEntity, PulseWasherOperateVO operateVO) {
        // 波轮洗衣机
        OperateParam param = new OperateParam();
        param.setImei(operateVO.getImei());
        param.setCmdName("grCommonWash");
        Map<String, String> cmdMap = new LinkedHashMap<>();
        // 洗衣程序, 1-7
        cmdMap.put("laundryCycleCW", Integer.toString(operateVO.getWashType()));
        // 消毒功能状态 true false
        cmdMap.put("disinfectionStatus", Boolean.toString(operateVO.isDisinfection()));
        //脉冲个数 0\1\2\4\8
        cmdMap.put("pulseNum", Integer.toString(operateVO.getPulseNum()));
        param.setCmdArgs(cmdMap);
        log.info("deviceId: " + deviceEntity.getId());

        return executeRequest(deviceEntity.getId(), "/modfier/operate", param, "operate", operateVO.getOrderId(), "pulseWash");
    }

    @Override
    public BaseResult doShoeWash(DeviceEntity deviceEntity, ShoeWasherOperateVO operateVO) {
        // 波轮洗衣机
        OperateParam param = new OperateParam();
        param.setImei(operateVO.getImei());
        param.setCmdName("grCommonWash");
        Map<String, String> cmdMap = new LinkedHashMap<>();
        // 洗衣程序, 1-7
        cmdMap.put("laundryCycleCW", Integer.toString(operateVO.getWashType()));
        // 消毒功能状态 true false
        cmdMap.put("disinfectionStatus", Boolean.toString(operateVO.isDisinfection()));
        //脉冲个数 0\1\2\4\8
        cmdMap.put("pulseNum", Integer.toString(operateVO.getPulseNum()));

        param.setCmdArgs(cmdMap);
        log.info("deviceId: " + deviceEntity.getId());
        return executeRequest(deviceEntity.getId(), "/modfier/operate", param, "operate", operateVO.getOrderId(), "shoeWash");
    }

    @Override
    public BaseResult doSendDeviceVerifyCode(DeviceEntity deviceEntity, String verifyCode) {
        // TODO
        return BaseResultFactory.produceEmptyResult(Code.ERROR, "暂不支持此操作");
    }

    @Override
    protected BaseResult<Map<String, String>> doGetProperties(DeviceEntity deviceEntity) {
        Map<String, String> map = new HashMap<>();
        map.put("deviceId", deviceEntity.getImei());
        // 请求
        String respResult = this.executeRequest("/modfier/getAttributeList", map);

        JSONObject jsonObject = JSONObject.parseObject(respResult);
        boolean success = jsonObject.get("retCode").equals("000000");
        // save invoke history
        InvokeHistoryEntity historyEntity = InvokeHistoryEntity.builder()
                .method("getAttributeList")
                .param(JSONObject.toJSONString(map))
                .orderId(null)
                .result("")
                .resultStatus(success ? "SUCCESS" : "FAILED")
                .userId(AuthenticationHolder.getUserId())
                .function("getPropertyByName")
                .deviceId(deviceEntity.getId())
                .build();
        invokeHistoryService.create(historyEntity);
        if (success) {
            JSONObject data = jsonObject.getJSONObject("data");
            JSONArray attributes = data.getJSONArray("attributes");
            Map<String, String> res = new HashMap<>();
            attributes.forEach(jsonObj -> {
                JSONObject obj = (JSONObject) jsonObj;
                String value = obj.getString("value");
                if (null != value) {
                    String name = obj.getString("name");
                    res.put(name, value);
                }
            });
            return BaseResultFactory.produceResult(Code.SUCCESS, res);
        } else {
            return BaseResultFactory.produceResult(Code.SUCCESS, null);
        }
    }

    /**
     * 执行请求
     *
     * @param deviceId
     * @param urlSuffix
     * @param param
     * @param operateMethod
     * @param function
     * @return
     */
    private BaseResult executeRequest(String deviceId, String urlSuffix, Object param, String operateMethod, String function) {
        return this.executeRequest(deviceId, urlSuffix, param, operateMethod, null, function);
    }

    /**
     * 执行请求
     *
     * @param deviceId
     * @param urlSuffix
     * @param param
     * @param operateMethod
     * @param orderId
     * @param function
     * @return
     */
    private BaseResult executeRequest(String deviceId, String urlSuffix, Object param, String operateMethod, String orderId, String function) {
        try {
            String respResult = this.executeRequest(urlSuffix, param);
            Map maps = JSONObject.parseObject(respResult, Map.class);
            String retCode = (String) maps.get("retCode");
            boolean success = retCode.equals("00000");
            // save invoke history
            InvokeHistoryEntity historyEntity = InvokeHistoryEntity.builder()
                    .method(operateMethod)
                    .param(JSONObject.toJSONString(param))
                    .orderId(orderId)
                    .result(respResult)
                    .resultStatus(success ? "SUCCESS" : "FAILED")
                    .userId(AuthenticationHolder.getUserId())
                    .function(function)
                    .deviceId(deviceId)
                    .build();
            invokeHistoryService.create(historyEntity);
            //调用成功
            if (success) {
                return BaseResultFactory.produceResult(Code.SUCCESS, respResult);
            } else if (retCode.equals("A00006") && maps.get("retInfo").equals("属性不存在")) {
                return BaseResultFactory.produceResult(Code.ERROR, "操作异常，请稍后重试");
            } else {
                return BaseResultFactory.produceResult(Code.ERROR, "查询异常，请稍后重试");
            }

        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return BaseResultFactory.produceResult(Code.ERROR, "系统异常，请稍后重试");
        }
    }

    private BaseResult<?> executeRequestWithoutHis(String urlSuffix, Object param) {
        try {
            String respResult = this.executeRequest(urlSuffix, param);
            Map maps = JSONObject.parseObject(respResult, Map.class);
            String retCode = (String) maps.get("retCode");
            boolean success = retCode.equals("00000");
            //调用成功
            if (success) {
                return BaseResultFactory.produceResult(Code.SUCCESS, respResult);
            } else if (retCode.equals("A00006") && maps.get("retInfo").equals("属性不存在")) {
                return BaseResultFactory.produceResult(Code.ERROR, "操作异常，请稍后重试");
            } else {
                return BaseResultFactory.produceResult(Code.ERROR, "查询异常，请稍后重试");
            }

        } catch (Exception e) {
            log.error(e.getMessage());
            return BaseResultFactory.produceResult(Code.ERROR, "系统异常，请稍后重试");
        }
    }

    /**
     * 执行请求
     *
     * @param urlSuffix
     * @param param
     * @return
     */
    private String executeRequest(String urlSuffix, Object param) {
        String jsonString = JSONObject.toJSONString(param);
        log.info("body: " + jsonString);
        String result = uhomeService.execute(urlSuffix, jsonString);
        log.info("call back result: " + result);
        return result;
    }

    @Override
    protected BaseResult doPumpStart(DeviceEntity deviceEntity, PumpWorkVO pumpWorkVO) {
        return BaseResultFactory.produceEmptyResult(Code.ERROR, "暂不支持此操作");
    }
}
